/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.annotation.AnNullable;
import org.zhiqim.kernel.constants.SignConstants;

/**
 * 列表相关工具类
 * 1.继承Collectionx类，实现基于集合的基础工具功能
 * 2.继承Listx类，实现基于的列表基础工具功能
 * 3.创建Lists类，实现扩展的列表功能
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Lists")
public class Lists extends Listx implements SignConstants
{
    /***********************************************************************************/
    //以下为拷贝出一个新的列表
    /***********************************************************************************/
    
    /** 拷贝到新列表中 */
    public static final <E> List<E> copy(List<E> list, boolean sync)
    {
        if (sync)
        {
            synchronized (list)
            {
                List<E> newList = new ArrayList<E>();
                for (E item : list){
                    newList.add(item);
                }
                
                return newList;
            }
        }
        else
        {
            List<E> newList = new ArrayList<E>();
            for (E item : list){
                newList.add(item);
            }
            
            return newList;
        }
    }
    
    /** 拷贝前n个到新列表中 */
    public static final <E> List<E> copy(List<E> list, int n)
    {
        List<E> newList = new ArrayList<E>();
        for (int i=0;i<n;i++){
            newList.add(list.get(i));
        }
        
        return newList;
    }
    
    /** 拷贝新的列表，并重新设置一个元素 */
    public static final <E> List<E> copySet(List<E> list, int index, E element)
    {
        List<E> newList = new ArrayList<>(list);
        newList.set(index, element);
        return newList;
    }
    
    /** 新拷贝一个列表，再增加一个元素 */
    public static final <E> List<E> copyAdd(List<E> list, E element)
    {
        List<E> newList = new ArrayList<>(list);
        newList.add(element);
        return newList;
    }
    
    /** 新拷贝一个列表，再增加一个元素到指定位置 */
    public static final <E> List<E> copyAdd(List<E> list, int index, E element)
    {
        List<E> newList = new ArrayList<>(list);
        newList.add(index, element);
        return newList;
    }
    
    /** 获取删除指定索引的新的列表 */
    public static final <E> List<E> copyRemove(List<E> list, int index)
    {
        List<E> newList = new ArrayList<>(list);
        newList.remove(index);
        return newList;
    }
    
    /***********************************************************************************/
    //以下为数组转为列表相关功能
    /***********************************************************************************/
    
    /** 清除ArrayList的size之外的无效引用 */
    public static <T> ArrayList<T> trim(ArrayList<T> list)
    {
        list.trimToSize();
        return list;
    }
    
    /** 清除ArrayList的size之外的无效引用 */
    public static <T> List<T> trim(List<T> list)
    {
        if (!(list instanceof ArrayList))
            return list;
        
        ((ArrayList<T>)list).trimToSize();
        return list;
    }
    
    /** 排序并返回对象 */
    public static <T> List<T> sort(List<T> list, Comparator<T> comparator)
    {
        if (!list.isEmpty())
            Collections.sort(list, comparator);
        return list;
    }
    
    /** 排序并返回对象 */
    public static <T> ArrayList<T> sort(ArrayList<T> list, Comparator<T> comparator)
    {
        if (!list.isEmpty())
            Collections.sort(list, comparator);
        return list;
    }
    
    /** 排序清理，并返回对象 */
    public static <T> ArrayList<T> sortAndTrim(ArrayList<T> list, Comparator<T> comparator)
    {
        if (!list.isEmpty())
            Collections.sort(list, comparator);
        list.trimToSize();
        return list;
    }
    
    /** 数组转列表 */
    public static <T> List<T> toList(T[] arr)
    {
        if (arr == null)
            return new ArrayList<T>();
        
        List<T> list = new ArrayList<T>(arr.length);
        for (T elem : arr)
            list.add(elem);
        
        return list;
    }
    
    /** int[]转列表 */
    public static List<Integer> toList(int[] arr)
    {
        return toList(Arrays.convert(arr));
    }
    
    /** long[]转列表 */
    public static List<Long> toList(long[] arr)
    {
        return toList(Arrays.convert(arr));
    }
    
    /** boolean[]转列表 */
    public static List<Boolean> toList(boolean[] arr)
    {
        return toList(Arrays.convert(arr));
    }
    
    /** float[]转列表 */
    public static List<Float> toList(float[] arr)
    {
        return toList(Arrays.convert(arr));
    }
    
    /** double[]转列表 */
    public static List<Double> toList(double[] arr)
    {
        return toList(Arrays.convert(arr));
    }
    
    /***********************************************************************************/
    //以下为列表和字符串转换相关功能
    /***********************************************************************************/
    
    /** 把字符串按逗号分隔转换成字符串数组，注意每个字符串都将trim()操作去除前后空字符串(空格,\r,\n,\t,\b等) */
    public static List<String> toStringList(String strs)
    {
        return toStringList(strs, ",");
    }
    
    /** 把字符串按split分隔转换成字符串数组，注意每个字符串都将trim()操作去除前后空字符串(空格,\r,\n,\t,\b等) */
    public static List<String> toStringList(String strs, String separator)
    {
        if (Validates.isEmpty(strs))
            return new ArrayList<String>();
        
        ArrayList<String> strList = new ArrayList<String>();
        String[] array = strs.split(separator);
        for (int i = 0; i < array.length; i++)
            strList.add(array[i].trim());
        
        strList.trimToSize();
        return strList;
    }
    
    /** 把字符串按逗号“,”分隔转换成整型列表 */
    public static List<Integer> toIntList(String strs)
    {
        return toIntList(strs, ",");
    }
    
    /** 把字符串按split分隔转换成整型列表 */
    public static List<Integer> toIntList(String strs, String separator)
    {
        List<String> strList = toStringList(strs, separator);
        return toIntList(strList);
    }
    
    /** 把字符串列表传换成整型列表 */
    public static List<Integer> toIntList(List<String> strList)
    {
        List<Integer> list = new ArrayList<Integer>(strList.size());
        for (String str : strList)
            list.add(Integer.parseInt(str.trim()));
        return list;
    }
    
    /** 把字符串按逗号“,”分隔转换成长整型列表 */
    public static List<Long> toLongList(String strs)
    {
        return toLongList(strs, ",");
    }
    
    /** 把字符串按split分隔转换成长整型列表 */
    public static List<Long> toLongList(String strs, String separator)
    {
        List<String> strList = toStringList(strs, separator);
        return toLongList(strList);
    }

    /** 把字符串列表转换成长整型列表 */
    public static List<Long> toLongList(List<String> strList)
    {
        List<Long> list = new ArrayList<Long>();
        for (String str : strList)
            list.add(Long.parseLong(str.trim()));
        return list;
    }
    
    /** 列表转换成逗号“,”分隔的字符串 */
    public static String toString(List<?> list)
    {
        return toString(list, ",");
    }
    
    /** 列表转换成分隔符分隔的字符串 */
    public static String toString(List<?> list, String separator)
    {
        if (list == null || list.size() == 0)
            return _EMPTY_;
        
        StringBuilder strb = new StringBuilder().append(list.get(0));
        for (int i=1;i<list.size();i++)
        {
            strb.append(separator).append(list.get(i));
        }

        return strb.toString();
    }
    
    /**
     * 列表初始化填充到指定索引位置
     * 
     * @param list          列表
     * @param toIndex       索引位置
     * @param elem          初始对象
     */
    public static <T> void fill(List<T> list, int toIndex, T elem)
    {
        while (list.size() < toIndex)
            list.add(elem);
    }
    
    /*********************************************/
    //以下列表相关工具功能
    /*********************************************/
    
    /** 列表位置反转倒序 */
    public static <T> ArrayList<T> reverse(ArrayList<T> oldList)
    {
        ArrayList<T> newList = new ArrayList<T>(oldList.size());
        for (int i=oldList.size()-1;i>=0;i--)
        {
            newList.add(oldList.get(i));
        }
        
        newList.trimToSize();
        return newList;
    }
    
    /**
     * 字符串s是否是含有通配符*的pattern能匹配上，如/abc/cde.gif匹配上/a*c/*de.*
     *
     * @param s         字符串
     * @param pattern   含通配符*的字符串，注意该方法中*至少占一个字符
     * @return          得到匹配的字符串列表
     */
    @AnNullable
    public static List<String> getMatchList(String s, String pattern)
    {
        if (s == null || pattern == null)
            return null;
        
        int ind = pattern.indexOf("*");
        if (ind == -1)
        {//如果匹配字符串不含通配符，则比较两字符串是否相等
            return s.equals(pattern)?new ArrayList<String>():null;
        }
        
        ArrayList<String> matchList = new ArrayList<>();
        while (true)
        {
            if (s.length() <= ind)
            {//长度不够没匹配上
                return null;
            }
            
            if (ind > 0)
            {//取出*号前面的内容
                String match = pattern.substring(0, ind);
                if (!s.startsWith(match))
                {//没有匹配上*号前面的内容
                    return null;
                }
                
                //抹除*号前面的内容，使得*号在第一个位置上
                pattern = pattern.substring(ind);
                s = s.substring(ind);
            }
            
            //去除*号
            pattern = pattern.substring(1);
            if (Validates.isEmpty(pattern))
            {//*号是最后一个字符表示成功
                matchList.add(s);
                matchList.trimToSize();
                return matchList;
            }
            
            //由于*号必须占一个字符，所以s也需要先去除一个字符再比较
            String temp = s.substring(0, 1);
            s = s.substring(1);
            
            //下一个*号
            ind = pattern.indexOf("*");
            if (ind == -1)
            {//后面没有*号，比较是否后缀匹配成功
                if (!s.endsWith(pattern))
                {//没匹配成功
                    return null;
                }
                
                //成功取通匹值
                String match = temp + Strings.trimRight(s, pattern);
                matchList.add(match);
                matchList.trimToSize();
                return matchList;
            }
            
            String match = pattern.substring(0, ind);
            int aInd = s.indexOf(match);
            if (aInd == -1)
                return null;
            
            if (aInd == 0)
            {//只匹配到一个字符
                matchList.add(temp);
            }
            else
            {//查到*号对应的内容，放置到通匹符表中，再去除进入下一个*号循环
                matchList.add(temp + s.substring(0, aInd));
                s = s.substring(aInd);
            }
        }
    }
}
